package org.jeecg.modules.building.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.jeecg.modules.building.entity.BuildingIncomeSummary;
import org.jeecg.modules.building.entity.TbBuilding;
import org.jeecg.modules.building.mapper.TbBuildingMapper;
import org.jeecg.modules.building.service.ITbBuildingService;
import org.jeecg.modules.system.entity.SysDepart;
import org.jeecg.modules.system.enums.OrgLevelEnum;
import org.jeecg.modules.system.mapper.SysDepartMapper;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 房屋明细表
 */
@Service
@Slf4j
public class TbBuildingServiceImpl extends ServiceImpl<TbBuildingMapper, TbBuilding> implements ITbBuildingService {
    @Resource
    TbBuildingMapper tbBuildingMapper;
    @Resource
    SysDepartMapper sysDepartMapper;

    @Override
    public List<TbBuilding> statistics(TbBuilding tbBuilding, Map<String, String[]> parameterMap) {
        List<TbBuilding> finalResult = new ArrayList<>();
        String[] depIds = parameterMap.get("companyId[]");
        if (depIds != null && depIds.length > 0 && !StringUtils.isEmpty(depIds[depIds.length - 1])) {
            String depId = depIds[depIds.length - 1];
            log.info("depId:{}", depId);
            SysDepart departById = sysDepartMapper.getDepartById(depId);
            String orgCode = departById.getOrgCode();
            tbBuilding.setCode(orgCode);
        }
        List<TbBuilding> tbBuildings = tbBuildingMapper.selectSummerList(tbBuilding);

        /**
         *  A01A13
         *  A01A13A13
         *  A01A12A13
         *  根据 code 字段进行分组
         */
        Map<String, List<TbBuilding>> data = tbBuildings.stream()
                .collect(Collectors.groupingBy(
                        TbBuilding::getCode,
                        LinkedHashMap::new, // 指定使用 LinkedHashMap
                        Collectors.toList()
                ));
        // 获取所有 key 的长度
        Set<Integer> uniqueLengths = new HashSet<>();
        for (String key : data.keySet()) {
            uniqueLengths.add(key.length());
        }

        // 将 Set 转换为数组
        int[] parentCodeLengths = uniqueLengths.stream().mapToInt(Integer::intValue).toArray();

        // 第一步 计算公司本部：对每个 key 的 List 中的收入进行汇总
        // 使用 Collectors.toMap 并指定使用 LinkedHashMap
        Map<String, BuildingIncomeSummary> summaryMap = data.entrySet().stream()
                .collect(Collectors.toMap(
                        Map.Entry::getKey,
                        entry -> {
                            BigDecimal sumBookArea = entry.getValue().stream()
                                    .map(TbBuilding::getBookArea)
                                    .filter(Objects::nonNull)
                                    .reduce(BigDecimal.ZERO, BigDecimal::add);
                            BigDecimal sumBookOriginalValue = entry.getValue().stream()
                                    .map(TbBuilding::getBookOriginalValue)
                                    .filter(Objects::nonNull)
                                    .reduce(BigDecimal.ZERO, BigDecimal::add);
                            BigDecimal sumBookNetValue = entry.getValue().stream()
                                    .map(TbBuilding::getBookNetValue)
                                    .filter(Objects::nonNull)
                                    .reduce(BigDecimal.ZERO, BigDecimal::add);
                            BigDecimal sumCardArea = entry.getValue().stream()
                                    .map(TbBuilding::getCardArea)
                                    .filter(Objects::nonNull)
                                    .reduce(BigDecimal.ZERO, BigDecimal::add);
                            BigDecimal sumNoCardArea = entry.getValue().stream()
                                    .map(TbBuilding::getNoCardArea)
                                    .filter(Objects::nonNull)
                                    .reduce(BigDecimal.ZERO, BigDecimal::add);
                            TbBuilding firstAssetManagement = entry.getValue().get(0);

                            BigDecimal sumValue = sumBookArea.add(sumBookOriginalValue).add(sumBookNetValue).add(sumCardArea).add(sumNoCardArea);
                            boolean flag = sumValue.compareTo(BigDecimal.ZERO) == 0;

                            String companyLevel = firstAssetManagement.getCompanyLevel();
                            if (StringUtils.isEmpty(companyLevel)) {
                                companyLevel = OrgLevelEnum.getLevelByCodeLength(firstAssetManagement.getCode().length());
                            }

                            return new BuildingIncomeSummary(
                                    firstAssetManagement.getCompanyName() + "（本部）合计",
                                    firstAssetManagement.getCode(),
                                    companyLevel,
                                    sumBookArea,
                                    sumBookNetValue,
                                    sumBookOriginalValue,
                                    sumCardArea,
                                    sumNoCardArea,
                                    flag ? new LinkedList<>() : entry.getValue()
                            );
                        },
                        (oldValue, newValue) -> oldValue, // 合并函数，这里直接返回 oldValue
                        LinkedHashMap::new // 指定使用 LinkedHashMap
                ));

        // 创建 currentSummaryMap 的深拷贝
        Map<String, BuildingIncomeSummary> currentSummaryMap = new LinkedHashMap<>();
        for (Map.Entry<String, BuildingIncomeSummary> entry : summaryMap.entrySet()) {
            currentSummaryMap.put(entry.getKey(), entry.getValue().deepCopy());
        }
        log.info("打印公司本部汇总数据 currentSummaryMap :{}", currentSummaryMap);

        for (Map.Entry<String, BuildingIncomeSummary> entry : summaryMap.entrySet()) {
            String code = entry.getKey();
            BuildingIncomeSummary summary = entry.getValue();
            aggregateToParent(summaryMap, code, summary, parentCodeLengths);
        }

        Map<String, BuildingIncomeSummary> containSummaryMap = new LinkedHashMap<>(summaryMap);
        for (Map.Entry<String, BuildingIncomeSummary> entry : summaryMap.entrySet()) {
            containSummaryMap.put(entry.getKey(), entry.getValue().deepCopy());
        }
        log.info("打印公司总计汇总数据 包含本部 containSummaryMap :{}", containSummaryMap);


        // 创建一个新的 CarSummary 对象用于汇总合计
        BuildingIncomeSummary totalSummary = getTotalSummary(currentSummaryMap);
        TbBuilding totalAssetManagement = new TbBuilding();
        BeanUtils.copyProperties(totalSummary, totalAssetManagement);
        finalResult.add(totalAssetManagement);

        // 第三步：将汇总结果和原始数据合并到一个 List 中
        for (BuildingIncomeSummary amount : containSummaryMap.values()) {

            TbBuilding amountAssetManagement = new TbBuilding();
            BeanUtils.copyProperties(amount, amountAssetManagement);
            finalResult.add(amountAssetManagement); //添加总计

            TbBuilding currentAssetManagement = new TbBuilding();
            BuildingIncomeSummary current = currentSummaryMap.get(amount.getCode());
            if (!amountAssetManagement.getCompanyName().equals(current.getCompanyName())) {
                BeanUtils.copyProperties(current, currentAssetManagement);
                finalResult.add(currentAssetManagement);//添加本部
            }

            finalResult.addAll(current.getBuildings()); //添加本部计算的原始数据
        }

        // 打印结果
        log.info("Final Result:{}", JSONObject.toJSONString(finalResult));
        /*        }*/
        return finalResult;
    }

    @NotNull
    private static BuildingIncomeSummary getTotalSummary(Map<String, BuildingIncomeSummary> currentSummaryMap) {
        BuildingIncomeSummary totalSummary = new BuildingIncomeSummary(
                "汇总合计", // 公司名称
                "", // 公司代码
                "", // 公司级次
                BigDecimal.ZERO, // 账面数-面积
                BigDecimal.ZERO, // 账面数-原值
                BigDecimal.ZERO, // 账面数-净值
                BigDecimal.ZERO, // 有证面积
                BigDecimal.ZERO, // 无证面积
                new ArrayList<>() // 资产列表
        );
        // 遍历 currentSummaryMap，将所有值汇总到 totalSummary
        for (BuildingIncomeSummary summary : currentSummaryMap.values()) {
            totalSummary.addBookArea(summary.getBookArea());
            totalSummary.addBookNetValue(summary.getBookNetValue());
            totalSummary.addBookOriginalValue(summary.getBookOriginalValue());
            totalSummary.addCardArea(summary.getCardArea());
            totalSummary.addNoCardArea(summary.getNoCardArea());
        }
        return totalSummary;
    }

    // 定义一个方法，用于将子公司的数据加和到父公司
    private static void aggregateToParent(Map<String, BuildingIncomeSummary> summaryMap, String code, BuildingIncomeSummary summary, int[] parentCodeLengths) {
        for (int length : parentCodeLengths) {
            if (code.length() > length) {
                String parentCode = code.substring(0, length); // 获取父公司的代码
                if (summaryMap.containsKey(parentCode)) {
                    // 将子公司的数据加和到父公司
                    BuildingIncomeSummary parentSummary = summaryMap.get(parentCode);
                    parentSummary.addBookArea(summary.getBookArea());
                    parentSummary.addBookNetValue(summary.getBookNetValue());
                    parentSummary.addBookOriginalValue(summary.getBookOriginalValue());
                    parentSummary.addCardArea(summary.getCardArea());
                    parentSummary.addNoCardArea(summary.getNoCardArea());
                    // 更新公司名称
                    String originalName = parentSummary.getCompanyName();
                    parentSummary.setCompanyName(originalName.replace("（本部）合计", "（公司）总计"));
                }
            }
        }
    }

}
